package org.github.manx98.jlibhac.tools.fssystem.romfs;

import org.github.manx98.jlibhac.fs.IStorage;
import org.github.manx98.jlibhac.fs.fsa.*;
import org.github.manx98.jlibhac.fssystem.BucketTree;

import java.io.IOException;

/**
 * @author Manx98
 * @version 1.0
 * @since 2022/10/4 2:07
 */
public class RomFsFileSystem extends IFileSystem {
    private final IStorage baseStorage;
    private final RomfsHeader header;
    protected final HierarchicalRomFileTable fileTable;

    public RomFsFileSystem(IStorage storage) throws IOException {
        this.baseStorage = storage;
        this.header = new RomfsHeader(storage.asFile(OpenMode.Read));

        IStorage dirHashTable = storage.slice(this.header.DirHashTableOffset, this.header.DirHashTableSize);
        IStorage dirEntryTable = storage.slice(this.header.DirMetaTableOffset, this.header.DirMetaTableSize);
        IStorage fileHashTable = storage.slice(this.header.FileHashTableOffset, this.header.FileHashTableSize);
        IStorage fileEntryTable = storage.slice(this.header.FileMetaTableOffset, this.header.FileMetaTableSize);

        this.fileTable = new HierarchicalRomFileTable(dirHashTable, dirEntryTable, fileHashTable, fileEntryTable);
    }

    @Override
    public IFile doOpenFile(String filePath, OpenMode mode) throws IOException {
        RomFileInfo info = fileTable.tryOpenFile(filePath);
        if (mode != OpenMode.Read){
            // RomFs files must be opened read-only.
            throw new IllegalArgumentException("Cannot open file " + filePath + ", RomFs files must be opened read-only!");
        }
        return new RomFsFile(baseStorage, header.DataOffset + info.Offset, info.Length);
    }

    @Override
    public IDirectory doOpenDirectory(String path, OpenDirectoryMode mode) throws IOException {
        FindPosition position = fileTable.tryOpenDirectory(path);
        return new RomFsDirectory(this, position, mode);
    }
}
